home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr35
/
dwnsrs57.zip
/
DOWNSRV.C
< prev
next >
Wrap
Text File
|
1993-06-25
|
37KB
|
925 lines
/* ============================================================= */
/* Rob Hamerling's MAXIMUS download file scan and sort utility. */
/* -> DOWNSRV.C */
/* -> Collection of general service routines for DOWNSORT. */
/* ============================================================= */
#define INCL_BASE
#define INCL_NOPMAPI
#include <os2.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "downsort.h"
#include "downfpro.h"
/* function prototype of local functions */
int comp_area(DOWNPATH *, DOWNPATH *);
/* ------------------- */
/* Welcome to the user */
/* ------------------- */
void show_welcome(void)
{
static char HD[22] = "══════════════════════";
printf("\n%15s╔%.22s╗\n", "", HD);
printf("╔%.14s╣ %8.8s version %c.%c%c╠%.15s╗\n",
HD,PROGNAME,VERSION,SUBVERS,SUFFIX,HD);
printf("║ Copyright ╚%.22s╝ Shareware ║\n", HD);
printf("║ %s %-38.38s║\n", MAX,PROGDESC);
printf("║ by %-13.13s, %-29s║\n", AUTHOR,CITY);
printf("║%-29s%24s║\n", PHONE, FIDO);
printf("╚%.22s%.22s%.9s╝\n", HD, HD, HD);
}
/* ======================================================== */
/* Compare two filenames. */
/* First name must be regular "8.3" format filename. */
/* Second name may contain wildcards. */
/* ======================================================== */
int wild_comp(char a[],
char b[])
{
int i;
char na[11], nb[11]; /* formatted filename fields */
/* keep 'm for subsequent calls */
static char empty_ext[] = { "..." }; /* files without ext. */
i = non_wild_init(8,na,a); /* init non-wild string */
switch(a[i]) { /* after fileNAME */
case ' ' :
case '\0':
i = non_wild_init(3,na+8,empty_ext); /* empty extension */
break;
case '.' :
i = non_wild_init(3,na+8,a+i+1); /* process extension */
break;
default: /* invalid filename */
i = non_wild_init(3,na+8,a+i); /* pseudo extension */
break;
}
i = wild_init(8,nb,b);
switch(b[i]) {
case ' ' :
case '\0':
i = wild_init(3,nb+8,empty_ext); /* empty extension */
break;
case '.' :
i = wild_init(3,nb+8,b+i+1); /* process extension */
break;
default: /* invalid filename */
i = wild_init(3,nb+8,b+i); /* pseaudo extension */
break;
}
#if defined(DEBUG2)
printf("\n"); /* debug of wild compare */
for (i=0; i<11; ++i)
printf("%c", (na[i] != '\0') ? na[i] : ' ');
printf(" ");
for (i=0; i<11; ++i)
printf("%02.2X", na[i]);
printf(" ");
for (i=0; i<11; ++i)
printf("%c", (nb[i] != '\0') ? nb[i] : ' ');
printf(" ");
for (i=0; i<11; ++i)
printf("%02.2X", nb[i]);
#endif
/* for (i=0; i<11 && (na[i]==nb[i] || na[i]=='\0' || nb[i]=='\0'); i++); */
for (i=0; i<11 && (na[i]==nb[i] || nb[i]=='\0'); i++);
#if defined(DEBUG2)
printf(" =#=%d",i); /* debug of wild compare */
#endif
if (i>=11) /* strings equal */
return(0);
else
return(na[i]-nb[i]);
}
/* ============================================ */
/* Init string for wild-card filenames compare. */
/* Translation to UPPER case. */
/* ============================================ */
int wild_init(short int n,
char p[],
char q[])
{
int i,j;
i=j=0;
while (i<n) { /* process string 'q' */
switch(q[j]) {
case '?': /* single wild char */
p[i++] = '\0'; /* matches with any other char */
j++; /* proceed with next char */
break;
case '.': /* end of filespec-part */
case ' ': /* logical end of string */
case '\0': /* end of string */
while (i<n) /* fill */
p[i++] = '.'; /* insert filler chars */
break;
case '*': /* wild string */
while (i<n) /* fill */
p[i++] = '\0'; /* matches with any other char */
j++; /* to next char */
break;
default: /* 'normal' characters */
p[i] = (char) toupper(q[i]); /* convert to UPPERcase and copy */
i++; j++; /* proceed with next char */
break;
}
}
return(j); /* displ. of last examined char */
}
/* ==================================================== */
/* Init string for non-wild-card filenames compare. */
/* No wild-cards expected, translation to upper case. */
/* ==================================================== */
int non_wild_init(short int n,
char p[],
char q[])
{
int i,j;
i=j=0;
while (i<n) { /* process string 'q' */
if (q[j]=='.' || q[j]==' ' || q[j]=='\0') {
p[i] = '.'; /* insert filler char */
i++; /* rest filler (no j-increment!) */
}
else {
p[i] = (char) toupper(q[i]); /* to UPPERcase and copy */
i++; j++; /* proceed with next char */
}
}
return(j); /* displ. of last examined char */
}
/* ------------------ */
/* Produce time stamp */
/* ------------------ */
char *sys_date(char t[])
{
long int secs_now; /* relative time value */
char *buf; /* pointer to time string */
time(&secs_now); /* get current time */
buf = ctime(&secs_now); /* convert to char string */
strcpy(t,buf); /* copy string */
t[16] = '\0'; /* undo secs, year and newline */
return(t); /* pointer to buffer */
}
/* ------------------------------------------------- */
/* Transform file-date into a 9-char string */
/* COUNTRY format mm-dd-yy (USA) or dd-mm-jj (EUR) */
/* ------------------------------------------------- */
char *f_date(struct _FDATE date)
{
static char string[9]; /* work buffer */
sprintf(string,"%2u%s%02u%s%02u",
((c_info.fsDateFmt == 0) ? date.month : date.day),
c_info.szDateSeparator,
((c_info.fsDateFmt == 0) ? date.day : date.month),
c_info.szDateSeparator,
(date.year+80)%100); /* allow 2 digits! */
return(string);
}
/* =================== */
/* determine file-age */
/* =================== */
char file_age_ind(struct _FDATE fd,
struct _FTIME ft)
{
long int age;
age = (time(NULL) - file_time(fd,ft))/86400L; /* days */
if (age>30)
return(' '); /* older than a month */
else {
if (age>7) /* older than 7 days */
return(DAYS_30);
else {
if (age>=0) /* non-negative negative age */
return(DAYS_7); /* a week */
else
return('-'); /* negative age */
}
}
}
/* -------------------------------------------------- */
/* Transform file-size and date into a 15-byte string */
/* Size in K (rounded to next higher number KBytes) */
/* Date format as inf_date(), plus age indicator. */
/* If date zero: pointer to 'offline'-text. */
/* -------------------------------------------------- */
char *f_size_date(unsigned long int size,
struct _FDATE wdate,
struct _FDATE cdate,
struct _FTIME ctime)
{
static char string[15]; /* work buffer */
if (wdate.day) { /* date non-zero */
sprintf(string,"%4luK ", (size+1023)/1024); /* format size */
strcat(string, f_date(wdate)); /* add formatted date */
string[14] = file_age_ind(cdate, ctime); /* add age ind. */
string[15] = '\0'; /* end of string */
return(string); /* for 'online' file */
}
else
return(OFFLINE); /* for 'offline' file */
}
/* -------------------------------------------------------------- */
/* Transform file-time into string (hh:mm:ssa) */
/* COUNTRY format hh:mm:ssa (12 hr USA) or hh-mm-ss (24 hr EUR) */
/* -------------------------------------------------------------- */
char *f_time(struct _FTIME tim)
{
static char time[7] = {'\0'}; /* work buffer */
sprintf(time,"%2u%s%02u%c%c",
(c_info.fsTimeFmt==0 && tim.hours>12) ? tim.hours-12 : tim.hours,
c_info.szTimeSeparator,
tim.minutes,
((c_info.fsTimeFmt==0) ? ((tim.hours>11) ? 'p' : 'a') : ' '),
'\0');
return(time);
}
/* ------------------------------ */
/* Build pointer-array for sorts */
/* ------------------------------ */
FILECHAIN **prep_sort(unsigned short int cnt,
struct _filechain *chn)
{
unsigned short int i; /* counter */
FILECHAIN **dm; /* pointer to file-sort array */
FILECHAIN *ca; /* pointer to fileinfo (chain) */
dm = (FILECHAIN **)malloc(cnt*sizeof(FILECHAIN *));
if (dm == NULL) { /* not enough memory */
printf(MSG_MEM,PROGNAME);
exit(11);
}
ca = chn; /* ptr to first file-info */
for (i=0; ca != NULL; i++) { /* init sort array */
dm[i] = ca;
ca = ca->next_element;
}
return(dm);
}
/* ====================================================== */
/* Compare for sort on file-date/time + filename + area */
/* ====================================================== */
int sort_new(const void *p,
const void *q)
{
int rc;
unsigned long int ad,bd,td;
FILECHAIN *a,*b;
a = *(FILECHAIN **)p;
b = *(FILECHAIN **)q;
ad = file_time(a->wdate,a->wtime);
td = file_time(a->cdate,a->ctime);
if (ad < td) /* take latest date */
ad = td;
bd = file_time(b->wdate,b->wtime);
td = file_time(b->cdate,b->ctime);
if (bd < td) /* take latest date */
bd = td;
if (bd==ad) { /* equal timestamps */
rc = strcmp(a->fname,b->fname);
if (rc) /* unequal filenames */
return(rc);
else
return(comp_area(a->parea, b->parea));
}
else
return( (int)((bd<ad) ? -1 : +1) );
}
/* ========================================= */
/* Compare for sort on filename + area-name */
/* ========================================= */
int sort_gbl(const void *p,
const void *q)
{
int rc;
FILECHAIN *a,*b;
a = *(FILECHAIN **)p;
b = *(FILECHAIN **)q;
rc = strcmp(a->fname,b->fname);
if (rc) /* unequal filename */
return(rc);
else
return(comp_area(a->parea, b->parea));
}
/* ======================================== */
/* Compare for sort on areaname + filename */
/* ======================================== */
int sort_all(const void *p,
const void *q)
{
int rc;
FILECHAIN *a,*b;
a = *(FILECHAIN **)p;
b = *(FILECHAIN **)q;
rc = comp_area(a->parea, b->parea);
if (rc) /* unequal areacode */
return(rc);
else
return(strcmp(a->fname,b->fname)); /* filename */
}
/* ======================================================== */
/* Compare for sort on areaname + file-date/time + filename */
/* ======================================================== */
int sort_al2(const void *p,
const void *q)
{
int rc;
unsigned long int ad,bd,td;
FILECHAIN *a,*b;
a = *(FILECHAIN **)p;
b = *(FILECHAIN **)q;
rc = comp_area(a->parea, b->parea);
if (rc) /* unequal area-name */
return(rc);
else {
ad = file_time(a->wdate,a->wtime);
td = file_time(a->cdate,a->ctime);
if (ad < td) /* take latest date */
ad = td;
bd = file_time(b->wdate,b->wtime);
td = file_time(b->cdate,b->ctime);
if (bd < td) /* take latest date */
bd = td;
if (bd!=ad) /* unequal date */
return( (int)((bd<ad) ? -1 : +1) );
else
return(strcmp(a->fname,b->fname)); /* filename */
}
}
/* ======================================================== */
/* Compare for sort on areaname + FILES.BBS sequence number */
/* ======================================================== */
int sort_akp(const void *p,
const void *q)
{
int rc;
FILECHAIN *a,*b;
a = *(FILECHAIN **)p;
b = *(FILECHAIN **)q;
rc = comp_area(a->parea, b->parea);
if (rc) /* unequal areacode */
return(rc);
else {
if (a->fseq != b->fseq) /* unequal sequence number */
return( (int)((a->fseq < b->fseq) ? -1 : +1) );
else
return(0); /* equal sequence number */
}
}
/* =================================================== */
/* Compare for sort on areaname + privilege + filename */
/* No sort on privilege if below area-privilege. */
/* =================================================== */
int sort_fil(const void *p,
const void *q)
{
int rc;
FILECHAIN *a,*b;
a = *(FILECHAIN **)p;
b = *(FILECHAIN **)q;
rc = comp_area(a->parea, b->parea);
if (rc) /* unequal areacode */
return(rc);
else {
if (a->priv <= a->parea->priv && /* both within area priv */
b->priv <= b->parea->priv)
return(strcmp(a->fname,b->fname)); /* sort on filename */
else if (a->priv == b->priv) /* same privilege */
return(strcmp(a->fname,b->fname)); /* filename */
else
return( (int)(a->priv - b->priv) ); /* file priv */
}
}
/* ========================================= */
/* Compare for sort on areaname of AREA-info */
/* ========================================= */
int sort_summ(const void *p,
const void *q)
{
return( comp_area((DOWNPATH *)p, (DOWNPATH *)q) );
}
/* ========================================= */
/* Compare for sort on areaname of AREA-info */
/* ========================================= */
int comp_area(DOWNPATH *p,
DOWNPATH *q)
{
int x,y; /* offsets in area_IN_EX */
switch(area_seq) {
case KEEPSEQ: return(p->anum - q->anum);
break;
case ALPHA: return(stricmp(p->name, q->name));
break;
case INCLUDE: if (area_IN_EX == +1) { /* areaINclude used */
for (x=0; strcmp(selected_area[x], EMPTY) &&
stricmp(selected_area[x], p->name);
x++); /* just determine x */
for (y=0; strcmp(selected_area[y], EMPTY) &&
stricmp(selected_area[y], q->name);
y++); /* just determine y */
if (x!=y) { /* if not equal */
return(x - y); /* relative position */
break; /* only if destinctive */
}
}
/* may fall back to group-order */
case GROUP: /* is default */
default: return(stricmp(p->ename, q->ename));
break;
}
}
/* ---------------------------- */
/* Sort file-info pointer array */
/* ---------------------------- */
void psort(FILECHAIN **arr,
short int left,
short int right,
int (*comp)(const void *, const void *))
{
int asc,desc;
FILECHAIN *ref,*tmp;
if ((right-left) < 1) /* too few elements */
return;
asc = left; /* left 'wall' */
desc = right; /* right 'wall' */
ref = arr[(left + right)/2]; /* reference value */
do {
while (comp(&arr[asc],&ref) < 0) /* move right */
asc++;
while (comp(&arr[desc],&ref) > 0) /* move left */
desc--;
if (asc <= desc) { /* swap */
tmp = arr[desc];
arr[desc--] = arr[asc];
arr[asc++] = tmp;
}
} while (asc <= desc);
if ((desc-left) < (right-asc)) { /* sort smaller part first */
if (left < desc)
psort(arr, left, desc, comp);
if (right > asc)
psort(arr, asc, right, comp);
}
else {
if (right > asc)
psort(arr, asc, right, comp);
if (left < desc)
psort(arr, left, desc, comp);
}
}
/* ============================================ */
/* Compare for newest acquisition in ALL-list */
/* ============================================ */
FILECHAIN *new_acq(FILECHAIN *a,
FILECHAIN *b)
{
long ad,bd,td;
if (b==NULL) /* right might be not assigned */
return(a); /* then return first */
ad = file_time(a->wdate,a->wtime);
td = file_time(a->cdate,a->ctime);
if (ad < td) /* take latest date */
ad = td;
bd = file_time(b->wdate,b->wtime);
td = file_time(b->cdate,b->ctime);
if (bd < td) /* take latest date */
bd = td;
if (ad==bd) /* equal dates */
return(b); /* (either) */
else
return((ad>bd) ? a : b); /* return most recent */
}
/* ============================================================== */
/* reformat file-date into long time-value like C time convention */
/* ============================================================== */
long int file_time(struct _FDATE fd,
struct _FTIME ft)
{
static int mon_tab[] = {0,31,59,90,120,151,181,212,243,273,304,334};
/* ignore leapyear February! */
return( 86400L *
(((fd.year+10)*1461+1)/4 + mon_tab[fd.month-1] + fd.day - 1) +
ft.hours * 3600 + ft.minutes * 60 + ft.twosecs * 2 );
}
/* =================================== */
/* Include a text file into a report. */
/* Output file is supposed to be open! */
/* =================================== */
void file_incl(FILE *pfo, /* output file pointer */
unsigned int fl) /* filelist id */
{
char buf[MAXRCD]; /* I/O buffer */
FILE *pfi; /* input file pointer */
if (lp[fl].incl_fspec != NULL) { /* filespec present */
if ((pfi = fopen(lp[fl].incl_fspec,"r")) != NULL) {
while (fgets(buf, MAXRCD, pfi) != NULL) { /* all records */
if (fl != P_FIL) /* all but FILES.BBS */
fputs(buf, pfo); /* "asis" */
else /* for FILES.BBS output */
fprintf(pfo,"%s %s", FILPREFX, buf); /* special prefix */
}
fclose(pfi);
}
else {
if (oper_mode == VERBOSE) /* report only in verbose mode */
printf(MSG_TRL,lp[fl].incl_fspec); /* file not included */
}
}
}
/* --------------------------------------------------------------- */
/* Produce file description parts for first and continuation lines */
/* --------------------------------------------------------------- */
void desc_part(FILE *pf, /* output file pointer */
char *desc, /* complete description */
unsigned int l1, /* length 1st part of descr. */
unsigned int l2, /* length of subsequent parts */
unsigned int fl) /* report structure index */
{
unsigned int k,n; /* length of part of string */
char *p; /* pointer to output string */
if (k = strsubw(desc, &p, l1)) { /* length (max = l1) */
if (lp[fl].wrapflag != WRAP) { /* truncate */
n = strlen(desc); /* total string length */
k = (l1 > n) ? n : l1; /* shortest of l1 and n */
}
fprintf(pf,"%-.*s\n", k, p); /* (1st part of) string */
while (k>0 && lp[fl].wrapflag==WRAP) /* more parts */
if (k = strsubw(p+k, &p, l2)) /* subseq. part */
fprintf(pf,"%*s%-.*s\n", 79-l2,"", k, p); /* 2nd+ descr parts */
}
}
/* ============================================================== */
/* routine to select a substring while skipping leading blanks */
/* and ending within the boundaries on a word-end. */
/* Truncate if single word. Respect NL as end of string. */
/* Return strlen, 0 for NULL-pointer. */
/* ============================================================== */
short int strsubw(char *a,
char **b,
short int m)
{
short int i,j,k; /* counters */
if (a==NULL) /* NULL pointer */
return(0); /* no string */
for (i=0; a[i] == ' '; ++i); /* skip leading blanks */
a = *b = a+i; /* offset to first non-blank char*/
for (i=0; a[i] != '\0' && a[i]!='\r' && a[i]!='\n'; ++i); /* search end*/
if (i==0) /* nothing left */
return(0); /* end! */
for (k=0; k<m && k<i; ++k); /* maximum substring */
if (k<i) { /* there is more in string */
if (a[k]==' ' || a[k]=='\r' || a[k]=='\n' || a[k]=='\0'); /*word end*/
else {
for (j=k-1; j>0 && a[j]!=' '; --j); /* try to remove 'split' word */
if (j>0) /* any space found? */
k = j; /* OK, else split! */
}
}
for (; k>0 && a[k-1] == ' '; --k); /* remove trailing blanks */
return(k); /* return length of substring */
/* b contains start-point */
}
/* ====================================================== */
/* Function to locate next non-blank character in buffer. */
/* Returns pointer to word or NULL-ptr if no next word. */
/* ====================================================== */
char *next_word(char *line)
{
unsigned int i;
for (i=0; line[i]!=' ' && /* skip non-blanks */
line[i]!='\r' &&
line[i]!='\n' &&
line[i]!='\0'; ++i);
for ( ; line[i]==' '; ++i); /* skip blanks */
if (line[i] != '\0' &&
line[i] != '\r' &&
line[i] != '\n')
return(line+i); /* next word found */
else
return(NULL); /* NULL if no next word */
}
/* =========================================== */
/* Function to make ASCIIZ string of ONE word. */
/* =========================================== */
char *asciiz(char *buf)
{
unsigned short int i;
for (i=0; buf[i] != ' ' && /* end copy at first blank */
buf[i] !='\r' && /* CR character */
buf[i] !='\n' && /* LF character */
buf[i] !='\0'; ++i) /* or end of string */
buf2[i] = buf[i]; /* copy */
buf2[i] = '\0'; /* end of string */
return(buf2); /* pointer to ASCIIZ string */
}
/* ============================================ */
/* Function to strip off AVATAR codes in string */
/* ============================================ */
char *strava(char *buf)
{
unsigned short int i, j, k, x; /* counters */
k = strlen(buf); /* length of source string */
for (i=j=0; i < k; ) { /* whole input string */
switch(buf[i]) {
case AVA_G:
case AVA_H:
case AVA_I:
case AVA_L: ++i; break;
case AVA_Y: for (x=0; x<buf[i+2]; x++)
buf2[j++] = buf[i+1]; /* repeat */
i += 3;
break;
case AVA_V: switch(buf[i+1]) {
case AVA_B:
case AVA_C:
case AVA_D:
case AVA_E:
case AVA_F:
case AVA_G:
case AVA_I:
case AVA_N: i += 2; break;
case AVA_A: i += 3; break;
case AVA_H: i += 4; break;
case AVA_L: i += 5; break;
case AVA_M: i += 6; break;
case AVA_J:
case AVA_K: i += 7; break;
case AVA_Y: i += 2; break;
default: buf2[j++]=buf[i++]; break;
}
break;
case '-': (i==0) ? i++ : (buf2[j++] = buf[i++]);
break;
default: buf2[j++] = buf[i++];
break;
}
}
buf2[j] = '\0'; /* end of string */
return(buf2); /* pointer to ASCIIZ string */
}
/* ========================================================= */
/* creates filecount and bytecount per area within privilege */
/* and pointer to most recent file in area */
/* returns total filecount all area's within priv. */
/* should be run before calling other count_functions below. */
/* ========================================================= */
unsigned int preproc_area(DOWNPATH *area,
FILECHAIN **dm,
short int priv)
{
unsigned int i; /* counter */
unsigned int fpc; /* total filecount within priv */
for (i=0; i<area_total_count; i++) { /* all area's in array */
area[i].file_count = 0; /* init filecount per area */
area[i].byte_count = 0L; /* init bytecount per area */
area[i].newest = NULL; /* null most-recent */
}
for (i=0; i<file_total_count; i++) { /* scan file-chain */
if (dm[i]->priv <= priv && /* file within privilege */
dm[i]->fname[0] != '\0') { /* not a 'comment' entry */
dm[i]->parea->file_count++; /* increment area filecount */
dm[i]->parea->byte_count += dm[i]->size; /* add filesize */
dm[i]->parea->newest = new_acq(dm[i], dm[i]->parea->newest);
}
}
fpc = 0; /* init total filecount */
for (i=0; i<area_total_count; i++) /* all area's in array */
fpc += area[i].file_count; /* sum of area file_counts */
return(fpc); /* return total file_count */
}
/* =========================================== */
/* count areas within privilege for top-header */
/* works only correctly after count_priv_files */
/* =========================================== */
unsigned int count_areas(DOWNPATH *area,
short int p)
{
unsigned int i,j;
for (i=j=0; i<area_total_count; i++) /* whole area-array */
if (area[i].priv <= p && /* area within privilege */
area[i].file_count > 0) /* any files */
++j; /* add to area_count */
return(j); /* return areas within priv. */
}
/* ================================================ */
/* (re-)Count files within privilege for top-header */
/* (file_priv_count already returns file-count) */
/* Works only correctly after preproc_area(). */
/* ================================================ */
unsigned int count_files(DOWNPATH *area)
{
unsigned int i,f;
for (i=f=0; i<area_total_count; i++) /* scan area array */
f += area[i].file_count; /* add to file_count */
return(f); /* return files within priv. */
}
/* =========================================== */
/* count bytes within privilege for top-header */
/* works only correctly after count_priv_files */
/* =========================================== */
unsigned long int count_bytes(DOWNPATH _HUGE *area)
{
unsigned short int i; /* counter */
unsigned long b; /* byte count */
for (i=0,b=0L; i<area_total_count; i++) /* scan area array */
b += area[i].byte_count; /* add to byte_count */
return(b); /* return bytes within priv. */
}
/* ==================================== */
/* insert title lines from DOWNSORT.CFG */
/* ==================================== */
void insert_title(FILE *pf,
char *title[],
int ipf) /* if not zero: call stripf() */
{
int i;
for (i=0; i<MAXTIT && title[i]!=NULL; ++i) /* all lines */
fprintf(pf,"%s\n",
(ipf) ? stripf(title[i]) : title[i]); /* 1 line */
}
/* ============================================================ */
/* insert separator line, variable number, separated by 1 blank */
/* ============================================================ */
void sep_line(FILE *pf, /* output file pointer */
char c, /* separator char */
unsigned short int size,...) /* length(s) */
{
char buf[80]; /* work buffer */
unsigned short int k,ll; /* offset and size */
va_list mk; /* argument marker */
memset(buf, c, 79); /* whole line buffer */
buf[79] = '\0'; /* end of string */
va_start(mk, size); /* start variable arg processing */
k = size; /* take first */
while (k < 80) { /* all parts of line */
buf[k++] = ' '; /* replace sepline char by space */
ll = va_arg(mk, unsigned short int); /* next argument */
if (ll > 0) /* more in list */
k += ll; /* add to offset */
else {
buf[k] = '\0'; /* end of string */
break; /* escape from while-loop */
}
}
fprintf(pf, "%-s\n", buf); /* output */
va_end(mk); /* end variable argument list */
}
/* ================== */
/* insert BLOCK title */
/* =================== */
void block_title(FILE *pf,
short int n,
char *title,
unsigned int listfile)
{
unsigned short int i;
for (i=0; i<title_lines[lp[listfile].tfont]; ++i) /* whole title */
fprintf(pf, "%s\n", strnblk(title, n, lp[listfile].tfont,i));
}
/* ================================== */
/* some marketing below every report! */
/* ================================== */
void signature(FILE *pf,
char *now)
{
static char *mode[] = {"DOS","OS/2"};
fprintf(pf,"\n\n ");
sep_line(pf, '═', 73, 0);
fprintf(pf," This list was created with %s %c.%c%c (%s-bits) - by %s\n"
" on %s under %s %d.%d\n ",
PROGNAME,VERSION,SUBVERS,SUFFIX,
#ifndef __32BIT__
"16",
#else
"32",
#endif
AUTHOR, now,
mode[_osmode & 1],
_osmajor/( (_osmode) ? 10 : 1),
_osminor/10);
sep_line(pf, '═', 73, 0);
fprintf(pf, "\n"); /* extra space */
}
/* ================ */
/* HELP information */
/* ================ */
void show_help(void)
{
static char *help[] = {
"Syntax: DOWNSORT [commandline-parameters]\n\n",
"@filespec - Filespec of Downsort's processing parameters\n",
"BBS[:p] - Make BBS-list ───┐\n",
"NEW[:pp] - Make NEW-list(s) │\n",
"EMI[:pp] - Make EMI-list(s) │ │for 1 or more privileges, where:\n",
"ALL[:pp] - Make ALL-list(s) ├─┤ p = first letter of privilege\n",
"IPF[:pp] - Make IPF-list(s) │ │ pp = max 10 privilege letters\n",
"IP2[:pp] - └-for OS/2 2.0+│ │ (N=Normal, P=Privil, etc)\n",
"GBL[:pp] - Make GBL-list(s) │\n",
"OK[:pp] - Make OKFile(s) │\n",
"DUP[:p] - Make DUP-list ───┘\n",
"ORP - Make ORP-list (if ORPHANS detected)\n",
"FIL[:fpath] - (re-)Create FILES.BBS files [in directory 'fpath']\n",
"nnn[P] - Limit NEW- and BBS-list by number, or age if P=D|W|M\n",
"-T|W - Long file descriptions to be Truncated or Wrapped\n",
"-A|D|K - Sort files Alphabetically, on Date, or Keep in FILES.BBS-seq.\n",
"-H|Q|V - Display this HELP-screen, or run Quietly or Verbose\n",
"-X - eXclude privilege indications in the lists\n",
"───────────\n",
"Commandline parameters override program and configuration-file values.\n"
"Read documentation and sample configuration file for details and defaults.\n",
NULL};
int i;
for (i=0; help[i]; ++i)
printf(help[i]);
exit(1);
}